(for Internet Explorer)
TestCase タグの子の SubCase タグに、別の TestCase タグの子を追加するときは、
aggregate 属性を使います。
<?xml version="1.0" encoding="Shift_JIS"?>
<TestCases>

<TestCase id="TestCase_for_T_Test1" aggregate="#TestCase_Common">
<SubCase  name="a" InputDataA="123" InputDataB="123"/>
</TestCase>

<TestCase id="TestCase_for_T_Test2" aggregate="#TestCase_Common">
<SubCase  name="b" InputDataA="123" InputDataB="ABC"/>
</TestCase>

<TestCase id="TestCase_Common">
<SubCase  name="c" InputDataA="ABC" InputDataB="ABC"/>
</TestCase>

</TestCases>
サンプル XML ファイル: T_Test1_Data.xml
<?xml version="1.0" encoding="Shift_JIS"?>
<TestCases>

<TestCase id="TestCase_for_T_Test1">
<SubCase  name="a" InputDataA="123" InputDataB="123"/>
<SubCase  name="c" InputDataA="ABC" InputDataB="ABC"/>
</TestCase>

<TestCase id="TestCase_for_T_Test2">
<SubCase  name="b" InputDataA="123" InputDataB="ABC"/>
<SubCase  name="c" InputDataA="ABC" InputDataB="ABC"/>
</TestCase>

</TestCases>
上のファイルと下のファイルは、同じデータになります。
TestCase_Common
TestCase_Common
TestCase_Common
テスト
→ T_TestCaseData.vbs # [T_BaseTestCaseData]
→ T_TestCaseData.xml # T_AggregateTestCaseData_1 など
SubCase
SubCase
SubCase
Sub  T_Test1( Opt, AppKey )
  Dim  x, y, mix

  Dim cases_x : Set cases_x = ReadTestCase( "T_Test1_Data.xml", "TestCase_for_T_Test1_x" )
  Dim cases_y : Set cases_y = ReadTestCase( "T_Test1_Data.xml", "TestCase_for_T_Test1_y" )
  Set mix = CreateObject( "Scripting.Dictionary" )
  For Each y  In cases_y.Items
    For Each x  In cases_x.Items
      mix.RemoveAll : Dic_add  mix, x : Dic_add  mix, y
      T_Test1_main  Opt, AppKey, mix
    Next
  Next
  Pass
End Sub

'// ループが増えてもインデントを深くさせないため、テストの実施は *_main 関数にする
Sub  T_Test1_main( Opt, AppKey, x )
  echo  x
  FuncA  x("InputData"), ReadFile( x("CurrentFolder") +"\file.txt" )
End Sub
<?xml version="1.0" encoding="UTF-8"?>
<TestCases>

<TestCase id="TestCase_for_T_Test1_x">
<SubCase  name="Number"
  InputData = "123"
  Answer    = "ans%Num%.txt"  _comment2= "FilePath with variable"
/>
<SubCase  name="Alphabet"
  InputData = "ABC"
  Answer    = "ans2.txt"
/>
</TestCase>

<TestCase id="TestCase_for_T_Test1_y"> <!-- This is cross case -->
<SubCase  name="CurrentFolder"
  CurrentFolder = "."
  StepPath      = "Data\"
/>
<SubCase  name="SubFolder"
  CurrentFolder = "Data"
  StepPath      = ""
/>
</TestCase>

</TestCases>
InputData
CurrentFolder
サンプル XML ファイル: T_Test1_Data.xml
テストケースの値が、表の縦軸と横軸にあり、表の全てをテストする場合は、下記のように二重ループに
して、Dic_add を使ってテストデータを結合します。
T_Test1
T_Test1
T_Test1
Sub  T_Test1( Opt, AppKey )
    Set t = CreateObject( "Scripting.Dictionary" )

    For Each  endian  In Array( "LittleEndian", "BigEndian" )
        For Each  language  In Array( "VBScript", "C" )
            t("Endian") = endian
            t("Language") = language
            T_Test1_Main  t
        Next
    Next

    Pass
End Sub


'// ループが増えてもインデントを深くさせないため、テストの実施は *_Main 関数にする
Sub  T_Test1_Main( Opt, AppKey, x )
  echo  x
  FuncA  x("Endian"), x("Language")
End Sub
Sub  T_Test1( Opt, AppKey )
  Dim  x

  Dim cases : Set cases = ReadTestCase( "T_Test1_Data.xml", "TestCase_for_T_Test1" )
  Set x = cases.LookUpDic( "name", "Alphabet" )
  T_Test1_main  Opt, AppKey, x
  Pass
End Sub
SubCase タグの中から、特定のタグだけ選択するときは、ArrayClass の LookUpDic を使ってください。
<?xml version="1.0" encoding="Shift_JIS"?>
<TestCases>

<TestCase id="TestCase_for_T_Test1">
<SubCase  name="Number"
  InputData = "123"
  Answer    = "ans%Num%.txt"
/>
<SubCase  name="Alphabet"
  InputData = "ABC"
  Answer    = "ans2.txt"
/>
</TestCase>

</TestCases>
サンプル XML ファイル: T_Test1_Data.xml
"name", "Alphabet"
Sub  T_Test1( Opt, AppKey )
  Dim  x, y

  Dim cases : Set cases_x = ReadTestCase( "T_Test1_Data.xml", "TestCase_for_T_Test1" )
  For Each x  In cases_x.Items
    For Each y  In Array( 2, 3 )
      x("y") = y
      T_Test1_main  Opt, AppKey, x
      x.Remove  "y"
    Next
  Next
  Pass
End Sub

'// ループが増えてもインデントを深くさせないため、テストの実施は *_main 関数にする
Sub  T_Test1_main( Opt, AppKey, x )
  echo  x
  FuncA  x("InputData"), ReadFile( x("y") +"\file.txt" )
End Sub
テストケースの値を XML ファイルではなく、スクリプトに埋め込む場合は、下記のように代入します。
x("y") = y
( 2, 3 )
T_Test1
T_Test1
T_Test1
x("y")
x.Remove  "y"
C言語の標準ライブラリだけを使うときは、fgets を使った1行ずつ読み込むような単純なファイル・リード
しかできませんが、VBScript で XML などのデータを整理することで、C言語のプログラムに複雑な
動きをさせることができるようになります。
Test.vbs
C言語のプログラム
T_Test1.xml
TempParams.txt
Sub  T_Test1_main( tests, x )  // x is from ReadTestCase
  Dim  f : Set f = OpenForWrite( "TempParams.txt", Empty )
  f.WriteLine  x("Param1") & " // Param1"
  f = Empty

  r= RunProg( "CLangProg.exe /TempParams:TempParams.txt", "" )

  del  "TempParams.txt"
vbs スクリプトのサンプル (Test.vbs)
int  Params_read( Params* m, FILE* f );

int  T_Sample()
{
  int         e;
  errno_t     et;
  FILE*       f = NULL;
  TCHAR       s[256];
  TCHAR       path[256];

  //=== ReadTestCase
  e= GetCommandLineNamed( _T("TempParams"), false, s, sizeof(s) ); IF(e)goto fin;
  e= StrT_getFullPath( path, sizeof(path), s, NULL );
  et= _tfopen_s( &f, path, _T("rt") ); IF(et)goto err_no;
  e= Params_read( &params, f ); IF(e)goto fin;

  //=== Test Main
  // Write here ...

  e=0;
fin:
  if(f!=NULL){ee= fclose( f ); IF(ee&&!e)e=E_Errno;}
}


int  Params_read( Params* m, FILE* f )
{
  int    e;
  int    i;
  TCHAR  line[256];

  line[0] = '\0';
  _fgetts( line, _countof(line), f );

  e= StrT_cutLineComment( line, sizeof(line), line, _T("//") ); IF(e)goto fin;
  m->BufferSize = _ttoi( line );

  _fgetts( line, _countof(line), f );  // skip space line
  e=0;
fin:
  return  e;
}
C言語のテスト・プログラムのサンプル (CLangProg.exe)
StrT_cutLineComment
TempParams.txt ファイルの データ型の名前
テスト・データが複数のデータ構造を持つときは、データ構造を識別するシンボルを
TempParams.txt ファイルに記述する必要があります。
DataTypeA  // データ型の名前
100        // DataTypeA の1つ目のデータ
200        // DataTypeA の2つ目のデータ

DataTypeB  // データ型の名前
100        // DataTypeB の1つ目のデータ
200        // DataTypeB の2つ目のデータ
300        // DataTypeB の3つ目のデータ
TempParams.txt ファイルの フラグド構造体パラメーター
→ フラグド構造体パラメーター
参考
TempParams.txt ファイルの基本形
100    // 1つ目のテスト・ケースの1つ目のデータ
200    // 1つ目のテスト・ケースの2つ目のデータ

110    // 2つ目のテスト・ケースの1つ目のデータ
210    // 2つ目のテスト・ケースの2つ目のデータ
多くの場合、テスト・データを単純に並べていくだけで、テストを実施することはできるでしょう。
テスト・ケースが複数あるときは、空行で区切るとよいでしょう。
clib の StrT_cutLineComment 関数を使えば、コメントを入れることができます。
下記は、struct { int a; int b; } TestData[2]; という構造になります。
1つのテスト・ケースにおいて、それぞれのデータを使うかどうかを表すには、1つ目のデータを
ビットフィールドの数値として使い、ビットが1であれば対応するデータが記述されているように
します。
0x07   // ビットフィールド。 ビット0、1、2が1
100    // 1つ目のデータ
200    // 2つ目のデータ
300    // 3つ目のデータ

0x02   // ビットフィールド。 ビット1のみが1
200    // 2つ目のデータ
TempParams.txt
TempParams.txt
TempParams.txt
If IsEmpty( g_ReadTestCase ) Then  Set g_ReadTestCase = new XmlObjReader
g_ReadTestCase.IsVerbose = True
Skipped
下記のように IsVerbose を True にすると、XML をリードする処理のステップを表示します。
Sub  SetReadTestCase( XmlPath as string, TestCaseID as string, Condition as string )
デバッグ用に、テストケースを指定します。
【引数】
XmlPath
TestCaseID
テストケースが書かれた XML ファイルのパス
XML ファイルの中の <TestCase> タグの id 属性の値
Condition
テストケースを指定する条件文
TestScript.vbs
ファイル:
Sub  T_Test1( Opt, AppKey )
  Dim  testcases, x

  SetReadTestCase  "T_Test1_Data.xml", "TestCase_for_T_Test1", "name='Alphabet'" : Skipped
  Set x = ReadTestCase( "T_Test1_Data.xml", "TestCase_for_T_Test1" )
  For Each x  In testcases.Items  '// x は、InputData="ABC" の1回ループのみになる
    T_Test1_main  Opt, AppKey, x
  Next
  Pass
End Sub
サンプル・コード:
<?xml version="1.0" encoding="UTF-8"?>
<TestCases>

<TestCase id="TestCase_for_T_Test1">
<SubCase  name="Number"
  InputData = "123"
  Answer    = "ans%Num%.txt"  _comment2= "FilePath with variable"
/>
<SubCase  name="Alphabet"
  InputData = "ABC"
  Answer    = "ans2.txt"
/>
</TestCase>

</TestCases>
サンプル XML ファイル: T_Test1_Data.xml
SetReadTestCase
を呼び出す前に、SetReadTestCase を呼び出すコードを追加すると、
ReadTestCase の返り値が、SetReadTestCase で指定した1つのケースだけになります。
(src)
テスト
→ T_TestCaseData.vbs # [T_SetReadTestCase]
Sub  SetStartSectionTree( SectionNames as string )
実行するセクションを設定します。
【引数】
SectionNames
セクション名。 CSV形式
ファイル:
vbslib.vbs
  SetStartSectionTree  "Sec1"
サンプル
  SetStartSectionTree  "Sec1, SubSec2"
サンプル
Sec1 セクションの中の SubSec2 セクションから実行します。
Sec1 セクションから実行します。
テスト
→ T_SectionTree.vbs # [T_SectionTree_SetStart]
(src)
関連
→ T_SectionTree.vbs # [T_SectionTree_SetStart2]
→ T_SectionTree.vbs # [T_SectionTree_SetStart3]
→ T_SectionTree.vbs # [T_SectionTree_SetStartMiss]
Sub  Pass
テストがパスしたことを、テストスクリプトに知らせて、プログラムを終了します。
(src)
内部的には、エラー 21 が発生します。
テスト
参考
→ T_SomeTests.vbs # T_TestReport
の T_SampA
Sub  Fail
テストが失敗したことを、ユーザーやテストスクリプトに知らせて、プログラムを終了します。
エラーが発生したときと同じ動きをします。つまり、Fail の後は実行しません。
(src)
テスト
→ T_SomeTests.vbs # T_TestReport
の T_SampB
Sub  Skip()
テストが実行できる状況ではないことを、テストスクリプトに知らせて、プログラムを終了します。
エラーが発生したときと同じ動きをします。つまり、Skip の後は実行しないで、次のテストを実行します。
(src)
テスト
→ T_SomeTests.vbs # T_TestReport
の T_SampC
Sub  Skipped
デバッグなどの理由で、テストの一部を一時的にスキップしたことを、テストスクリプトに
知らせます。 Skipped を呼んだテスト項目は、Pass を呼び出しても Fail します。
このときのエラーメッセージは、次のようになります。
(src)
Pass But Skipped. Cut calling "Skipped" function.
テスト
Sub  ManualTest( TestSymbol as string )
テストが手動テストであることを、テストスクリプトに知らせます。
ManualTest  tests.Symbol
サンプル
参考
(src)
手動テストは最低限にしてください。
ManualTest  "T_Sample1"
参考
Sub  Assert( Condition as boolean )
条件が満たされているかをチェックします。
満たされていなければ、Fail を呼び出します。
If not Condition Then  Fail とほぼ同じですが(違いは下記)、正しい条件文を記述する
ことになるので、ソースの可読性があがります。
また、If 文を使わないので、マルチステートメント(1行に複数の文)が記述できます。
g_debug の設定にかかわらず常にチェックします。
Public Property Let  VarA(x) : Assert x >= 0 : VarA = x : End Property
(src)
If Condition と If not Condition は、完全に反対の関係ではありません。
たとえば、If 4 と If not 4 は、どちらも真です。
完全に反対の関係は次のように複数行になります。
  If Condition Then
  Else
    ***
  End If
よって、正しい条件文を記述することは If Then Fail より Assert の方が簡単になります。
x >= 0
関連
テストが失敗したことを、ユーザーやテストスクリプトに知らせます。
新規にエラーを発生させます。
サンプル
トラブルシューティング
左辺全体を括弧で囲むと、エラーになります。
Assert  ( a + 2 ) = 0  '// エラー: 型が一致しません。: 'Assert'
上記は、( a + 2 ) = 0 の評価を行ってから Assert を呼び出すのではなく、
a + 2 を配列番号とした Assert 配列に 0 を代入するように解釈されます。
Assert  a + 2 = 0
Assert  ( ( a + 2 ) = 0 )
以下のように括弧を削除するか、括弧を追加してください。
Sub  AssertExist( in_Path as string )
ファイルまたはフォルダが存在するかどうかをチェックします。
AssertExist  "settings.txt"
サンプル:
→ vbslib.vbs
存在しなければ、エラーメッセージの中にパスが含まれます。
このため、デバッガを起動しなくてもユーザーが対応できる可能性が高まります。
エラーコードは、E_PathNotFound になります。
逆に、AssertExist では、存在するときにエラーにすることはできません。
"settings.txt"
エラーメッセージのサンプル:
<ERROR msg="ファイルまたはフォルダーが見つかりません" path="C:\Folder\setting.txt"/>
→ T_File.vbs
テスト
関連
参考
Test.vbs で共通のファイルの存在チェック
ソース
T_AssertExist_UNC
T_AssertExist
→ T_FileMutex_Manually.vbs
大文字小文字が異なると、echo_v 関数で警告を表示しますが、継続します。
<WARNING msg="大文字小文字が異なります" call="C:\file.txt" name="C:\File.txt"/>
→ 大文字小文字に統一することの副作用
→ vbslib_mini.vbs
Sub  Assert2Exist( in_PathA as string,  in_PathB as string )
ファイルまたはフォルダが2つとも存在するかどうかをチェックします。
1つでも存在しなければ、エラーメッセージの中に2つのパスが含まれます。
2つを比較するときに使うとよいでしょう。
このため、デバッガを起動しなくてもユーザーが対応できる可能性が高まります。
エラーコードは、E_PathNotFound になります。
大文字小文字が異なると、echo_v 関数で警告を表示しますが、継続します。
Assert2Exist  "FileA.txt", "FileB.txt"
サンプル:
"FileA.txt", "FileB.txt"
エラーメッセージのサンプル:
<ERROR msg="片方または両方のファイルまたはフォルダーが見つかりません"
 path_A="C:\Folder\FileA.txt"
 path_B="C:\Folder\FileB.txt"
 not_exist="A,B"/>
<WARNING msg="大文字小文字が異なります" call="C:\file.txt" name="C:\File.txt"/>
→ vbslib.vbs
→ T_File.vbs
テスト
ソース
T_Assert2Exist
関連
AssertFullPath
Sub  AssertFullPath( in_Path as string,  in_NameOfPath as string )
指定したパスがフル パスでなければ、エラーにします。
【引数】
in_Path
in_NameOfPath
調べるパス
in_Path に指定したパスを設定する場所(表示用)
フル パスでなければ、次のエラーメッセージを表示します。
→ vbslib.vbs
ソース
<ERROR msg="フル パスを設定してください。
可能ならフル パスの先頭は変数にしてください。"
name="Tag/@file"  path="Sub\File.txt"/>"
XML ファイルに
が指定できるなら、
ことで、${ } 変数にフル パスを設定することができます。
たとえば、XML ファイルの一部を次のように記述します。
<Variable  name="${Base}"  value=".."  type="FullPathType"/>
<Tag file="${Base}\File.txt"/> ... file 属性はフル パス
${Base}\File.txt
変数 ${Base} の値は、XML ファイルがあるフォルダーの親フォルダーのフル パスです。
Sub  AssertFC( Path1 as string, Path2 as string )
2つのテキストファイルを比較して、異なれば diff ツールを開きます。
テキストファイルの文字コードが自動判定できるなら、文字コードが異なっても
テキストが同じであれば、同じと判定します。
文字コードが異なれば必ず異なると判定するときは、
参考
Path2 のファイルの内容に、% を使った文字列変換関数を使うことができます。
% 文字を使うとき(文字列変換関数からエスケープするとき)は、%% と記述します。
を使ってください。
テスト
c.RightHasPercentFunction or c.ErrorIfNotSame のケース
テキスト ファイルの内容の大文字と小文字を区別しません。
ソース
→ TestScript.vbs
Sub  T_Sample( Opt, AppKey )
    Set w_= AppKey.NewWritable( Array( "_out.txt" ) ).Enable()

    RunProg  "cscript //nologo "+ WScript.ScriptName +" T_Sample_Sub", "_out.txt"

    AssertFC  "_out.txt", "T_Sample_ans.txt"
    del  "_out.txt"

    Pass
End Sub

Sub  T_Sample_Sub( Opt, AppKey )
    '// 標準出力へ出力する処理
End Sub
サンプル
AssertFC
→ T_fc_Manually.vbs
T_AssertFC
g_Vers("AssertFC_Diff") = False
下記のコードを書いた後は、diff ツールが開かなくなります。
下記のコードがあってもなくても、例外は発生します。
異なっていたら、E_TestFail エラーになります。
→ vbslib.vbs
AssertFC
関連
→ AssertFC フォルダー
比較の詳細を調べたいときは、IsSameTextFile 関数
(vbslib.vbs)
の中で is_debugging
を検索して見つかるソース コードを参照してください。